from django.db import models
from django.contrib.auth.models import User


class Asset(models.Model):
    # 所有资产的共有数据表
    asset_type_choice = (
        ('server', '服务器'),
        ('networkdevice', '网络设备'),
        ('storagedevice', '存储设备'),
        ('securitydevice', '安全设备'),
        ('software', '软件资产'),
    )

    asset_status = (
        (0, '在线'),
        (1, '下线'),
        (2, '未知'),
        (3, '故障'),
        (4, '备用'),
    )

    asset_type = models.CharField(choices=asset_type_choice, max_length=64, default='server', verbose_name=u'资产类型')
    name = models.CharField(max_length=64, unique=True, verbose_name=u'资产名称')
    sn = models.CharField(max_length=64, unique=True, verbose_name=u'资产序列号')
    business_unit = models.ForeignKey('BusinessUnit', null=True, blank=True, verbose_name=u'所属业务线',
                                      on_delete=models.CASCADE)
    status = models.SmallIntegerField(choices=asset_status, default=0, verbose_name=u'设备状态')
    manufacturer = models.ForeignKey('Manufacturer', null=True, blank=True, verbose_name=u'制造商',
                                     on_delete=models.CASCADE)
    manage_ip = models.GenericIPAddressField(null=True, blank=True, verbose_name=u'管理IP')
    tags = models.ManyToManyField('Tag', blank=True, verbose_name=u'标签')
    admin = models.ForeignKey(User, null=True, blank=True, verbose_name=u'资产管理员', related_name='admin',
                              on_delete=models.CASCADE)
    idc = models.ForeignKey('IDC', null=True, blank=True, verbose_name=u'所在机房', on_delete=models.CASCADE)
    contract = models.ForeignKey('Contract', null=True, blank=True, verbose_name=u'合同', on_delete=models.CASCADE)
    purcase_day = models.DateField(null=True, blank=True, verbose_name=u'购买日期')
    expire_day = models.DateField(null=True, blank=True, verbose_name=u'过保日期')
    price = models.FloatField(null=True, blank=True, verbose_name=u'价格')
    approved_by = models.ForeignKey(User, null=True, blank=True, verbose_name=u'批准人', related_name='approved_by',
                                    on_delete=models.CASCADE)
    memo = models.TextField(null=True, blank=True, verbose_name=u'备注')
    c_time = models.DateTimeField(auto_now_add=True, verbose_name=u'批准日期')
    m_time = models.DateTimeField(auto_now_add=True, verbose_name=u'更新日期')

    def __str__(self):
        return '<%s> <%s>' % (self.get_asset_type_display(), self.name)

    class Meta:
        verbose_name = '资产总表'
        verbose_name_plural = verbose_name
        ordering = ['-c_time']


# 服务器设备
class Server(models.Model):
    sub_asset_type_choice = (
        (0, 'PC服务器'),
        (1, '刀片机'),
        (2, '小型机'),
    )

    created_by_choice = (
        ('auto', '自动添加'),
        ('manual', '手动录入'),
    )

    asset = models.OneToOneField('Asset', on_delete=models.CASCADE)
    sub_asset_type = models.SmallIntegerField(verbose_name=u'服务器类型', choices=sub_asset_type_choice, default=0)
    created_by = models.CharField(verbose_name=u'添加方式', choices=created_by_choice, max_length=32, default='auto')
    hosted_on = models.ForeignKey('self', related_name='hosted_on_server', blank=True, null=True, verbose_name=u'宿主机',
                                  on_delete=models.CASCADE)
    model = models.CharField(verbose_name=u'Raid类型', max_length=128, null=True, blank=True)
    os_type = models.CharField(verbose_name=u'操作系统类型', max_length=64, blank=True, null=True)
    os_distribution = models.CharField(verbose_name=u'发行版本', max_length=64, blank=True, null=True)
    os_release = models.CharField(verbose_name=u'操作系统版本', max_length=64, blank=True, null=True)

    def __str__(self):
        return '%s--%s--%s <sn:%s>' % (self.asset.name, self.get_sub_asset_type_display(), self.model, self.asset.sn)

    class Meta:
        verbose_name = '服务器'
        verbose_name_plural = verbose_name


# 安全设备
class SecurityDevice(models.Model):
    sub_asset_type_choice = (
        (0, '防火墙'),
        (1, '入侵检测设备'),
        (2, '互联网网关'),
        (3, '运维审计系统'),
    )

    asset = models.OneToOneField('Asset', on_delete=models.CASCADE)
    sub_asset_type = models.SmallIntegerField(verbose_name=u'安全设备类型', choices=sub_asset_type_choice, default=0)

    def __str__(self):
        return self.asset.name + '--' + self.get_sub_asset_type_display() + 'id:%s' % self.id

    class Meta:
        verbose_name = '安全设备'
        verbose_name_plural = verbose_name


# 存储设备
class StorageDevice(models.Model):
    sub_asset_type_choice = (
        (0, '磁盘阵列'),
        (1, '网络存储器'),
        (2, '磁带库'),
        (3, '磁带机'),
    )

    asset = models.OneToOneField('Asset', on_delete=models.CASCADE)
    sub_asset_type = models.IntegerField(verbose_name=u'存储设备类型', choices=sub_asset_type_choice, default=0)

    def __str__(self):
        return self.asset.name + '--' + self.get_sub_asset_type_display() + 'id:%s' % self.id

    class Meta:
        verbose_name = '存储设备'
        verbose_name_plural = verbose_name


#  网络设备
class NetworkDevice(models.Model):
    sub_asset_type_choice = (
        (0, '路由器'),
        (1, '交换机'),
        (2, '负载均衡'),
        (3, 'VPN设备'),
    )

    asset = models.OneToOneField('Asset', on_delete=models.CASCADE)
    sub_asset_type = models.SmallIntegerField(verbose_name=u'网络设备类型', choices=sub_asset_type_choice, default=0)
    vlan_ip = models.GenericIPAddressField(verbose_name=u'VLanIP', blank=True, null=True)
    intranet_ip = models.GenericIPAddressField(verbose_name=u'内网IP', blank=True, null=True)
    model = models.CharField(verbose_name=u'网络设备型号', max_length=128, null=True, blank=True)
    firmware = models.CharField(verbose_name=u'设备固件版本', max_length=128, blank=True, null=True)
    port_num = models.SmallIntegerField(verbose_name=u'端口个数', null=True, blank=True)
    device_detail = models.TextField(verbose_name=u'详细配置', null=True, blank=True)

    def __str__(self):
        return '%s--%s--%s <sn:%s>' % (self.asset.name, self.get_sub_asset_type_display(), self.model, self.asset.sn)

    class Meta:
        verbose_name = '网络设备'
        verbose_name_plural = verbose_name


# 只保存付费购买的软件
class Software(models.Model):
    sub_asset_type_choice = (
        (0, '操作系统'),
        (1, '办公/开发软件'),
        (2, '业务软件'),
    )

    sub_asset_type = models.SmallIntegerField(verbose_name=u'软件类型', choices=sub_asset_type_choice, default=0)
    license_num = models.IntegerField(verbose_name=u'授权数量', default=1)
    version = models.CharField(verbose_name=u'软件/系统版本', max_length=32, unique=True,
                               help_text=u'例如: CentOS release 6.5(Final)')

    def __str__(self):
        return '%s--%s' % (self.get_sub_asset_type_display(), self.version)

    class Meta:
        verbose_name = '软件/系统'
        verbose_name_plural = verbose_name


# 机房
class IDC(models.Model):
    name = models.CharField(verbose_name=u'机房名称', max_length=64, unique=True)
    memo = models.CharField(verbose_name=u'备注', max_length=128, blank=True, unique=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '机房'
        verbose_name_plural = verbose_name


# 厂商
class Manufacturer(models.Model):
    name = models.CharField(verbose_name=u'厂商名称', max_length=64, unique=True)
    telephone = models.CharField(verbose_name=u'支持电话', max_length=64, unique=True)
    memo = models.CharField(verbose_name=u'备注', max_length=64, unique=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '厂商'
        verbose_name_plural = verbose_name


# 业务线
class BusinessUnit(models.Model):
    parent_unit = models.ForeignKey('self', blank=True, null=True, related_name='parent_level',
                                    on_delete=models.CASCADE)
    name = models.CharField(verbose_name=u'业务线', max_length=64, unique=True)
    demo = models.CharField(verbose_name=u'备注', max_length=64, blank=True, null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '业务线'
        verbose_name_plural = verbose_name


# 合同
class Contract(models.Model):
    sn = models.CharField(verbose_name=u'合同号', max_length=128, unique=True)
    name = models.CharField(verbose_name=u'合同名称', max_length=64)
    memo = models.TextField(verbose_name=u'备注', blank=True, null=True)
    price = models.IntegerField(verbose_name=u'合同金额')
    detail = models.TextField(verbose_name=u'合同详情', blank=True, null=True)
    start_day = models.DateField(verbose_name=u'开始日期', blank=True, null=True)
    end_day = models.DateField(verbose_name=u'失效日期', blank=True, null=True)
    license_num = models.IntegerField(verbose_name=u'license数量', blank=True, null=True)
    c_day = models.DateField(verbose_name=u'创建日期', auto_now_add=True)
    m_day = models.DateField(verbose_name=u'修改日期', auto_now=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '合同'
        verbose_name_plural = verbose_name


# 标签
class Tag(models.Model):
    name = models.CharField(verbose_name=u'标签名', max_length=32, unique=True)
    c_day = models.DateField(verbose_name=u'创建日期', auto_now_add=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '标签'
        verbose_name_plural = verbose_name


# CPU
class CPU(models.Model):
    asset = models.OneToOneField('Asset', on_delete=models.CASCADE)
    cpu_model = models.CharField(verbose_name=u'CPU型号', max_length=128, blank=True, null=True)
    cpu_count = models.PositiveSmallIntegerField(verbose_name=u'物理CPU个数', default=1)
    cpu_core_count = models.PositiveSmallIntegerField(verbose_name=u'CPU核数', default=1)

    def __str__(self):
        return self.asset.name + ': ' + self.cpu_model

    class Meta:
        verbose_name = 'CPU'
        verbose_name_plural = verbose_name


# 内存组件
class RAM(models.Model):
    asset = models.ForeignKey('Asset', on_delete=models.CASCADE)
    sn = models.CharField(verbose_name=u'SN号', max_length=128, blank=True, null=True)
    model = models.CharField(verbose_name=u'内存型号', max_length=128, blank=True, null=True)
    manufacturer = models.CharField(verbose_name=u'内存制造商', max_length=128, blank=True, null=True)
    slot = models.CharField(verbose_name=u'插槽', max_length=64)
    capacity = models.IntegerField(verbose_name=u'内存大小(GB)', blank=True, null=True)

    def __str__(self):
        return '%s: %s: %s: %s' % (self.asset.name, self.model, self.slot, self.capacity)

    class Meta:
        verbose_name = '内存'
        verbose_name_plural = verbose_name
        # 同一资产下的内存，根据插槽的不同，必须唯一
        unique_together = ('asset', 'slot')


# 硬盘模型
class Disk(models.Model):
    disk_interface_type_choice = (
        ('SATA', 'SATA'),
        ('SAS', 'SAS'),
        ('SCSI', 'SCSI'),
        ('SSD', 'SSD'),
        ('unknown', 'unknown'),
    )

    asset = models.ForeignKey('Asset', on_delete=models.CASCADE)
    sn = models.CharField(verbose_name=u'硬盘SN号', max_length=128)
    slot = models.CharField(verbose_name=u'所在插槽位', max_length=64, blank=True, null=True)
    model = models.CharField(verbose_name=u'磁盘型号', max_length=128, blank=True, null=True)
    manufacturer = models.CharField(verbose_name=u'磁盘制造商', max_length=128, blank=True, null=True)
    capacity = models.FloatField(verbose_name=u'磁盘容量(GB)', blank=True, null=True)
    interface_type = models.CharField(verbose_name=u'接口类型', max_length=16, choices=disk_interface_type_choice,
                                      default='unknown')

    def __str__(self):
        return '%s: %s: %s: %sGB' % (self.asset.name, self.model, self.slot, self.capacity)

    class Meta:
        verbose_name = '硬盘'
        verbose_name_plural = verbose_name
        unique_together = ('asset', 'sn')


# 网卡模型
class NIC(models.Model):
    asset = models.ForeignKey('Asset', on_delete=models.CASCADE)
    name = models.CharField(verbose_name=u'网卡名称', max_length=64, blank=True, null=True)
    model = models.CharField(verbose_name=u'网卡型号', max_length=128)
    mac = models.CharField(verbose_name=u'MAC地址', max_length=64)
    id_address = models.GenericIPAddressField(verbose_name=u'IP地址', max_length=128, blank=True, null=True)
    net_mask = models.CharField(verbose_name=u'掩码', max_length=32, blank=True, null=True)
    bonding = models.CharField(verbose_name=u'绑定地址', max_length=16, blank=True, null=True)

    def __str__(self):
        return '%s: %s: %s' % (self.asset.name, self.model, self.mac)

    class Meta:
        verbose_name = '网卡'
        verbose_name_plural = verbose_name
        unique_together = ('asset', 'model', 'mac')


# 日志模型
class EventLog(models.Model):
    event_type_choice = (
        (0, '其他'),
        (1, '硬件变更'),
        (2, '新增配件'),
        (3, '设备下线'),
        (4, '设备上线'),
        (5, '定期维护'),
        (6, '业务上线/更新/变更'),
    )
    name = models.CharField(verbose_name=u'事件名称', max_length=128)
    new_asset = models.ForeignKey('NewAssetApprovalZone', blank=True, null=True, on_delete=models.CASCADE)
    event_type = models.SmallIntegerField(verbose_name=u'事件类型', choices=event_type_choice, default=0)
    component = models.CharField(verbose_name=u'事件子项', max_length=256, blank=True, null=True)
    detail = models.TextField(verbose_name=u'事件详情')
    date = models.DateTimeField(verbose_name=u'事件时间', auto_now_add=True)
    user = models.ForeignKey(User, blank=True, null=True, verbose_name=u'事件执行人', on_delete=models.CASCADE)
    memo = models.TextField(verbose_name=u'备注', blank=True, null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '事件记录'
        verbose_name_plural = verbose_name


# 新资产待审批区模型
class NewAssetApprovalZone(models.Model):
    sn = models.CharField('资产SN号', max_length=128, unique=True)
    asset_type_choice = (
        ('server', '服务器'),
        ('networkdevice', '网络设备'),
        ('storagedevice', '存储设备'),
        ('securitydevice', '安全设备'),
        ('IDC', '机房'),
        ('software', '软件资产'),
    )

    asset_type = models.CharField(verbose_name=u'资产类型', choices=asset_type_choice, default='server', max_length=64,
                                  blank=True, null=True)
    manufacturer = models.CharField(verbose_name=u'生产厂商', max_length=128, blank=True, null=True)
    model = models.CharField(verbose_name=u'型号', max_length=128, blank=True, null=True)
    ram_size = models.PositiveIntegerField(verbose_name=u'内存大小', blank=True, null=True)
    cpu_model = models.CharField(verbose_name=u'CPU型号', max_length=128, blank=True, null=True)
    cpu_count = models.PositiveSmallIntegerField(blank=True, null=True)
    cpu_core_count = models.PositiveSmallIntegerField(blank=True, null=True)
    os_distribution = models.CharField(max_length=64, blank=True, null=True)
    os_type = models.CharField(max_length=64, blank=True, null=True)
    os_release = models.CharField(max_length=64, blank=True, null=True)
    data = models.TextField(verbose_name=u'资产数据')
    c_time = models.DateTimeField(verbose_name=u'汇报日期', auto_now_add=True)
    m_time = models.DateTimeField(verbose_name=u'数据更新日期', auto_now=True)
    approved = models.BooleanField(verbose_name=u'是否批准', default=False)

    def __str__(self):
        return self.sn

    class Meta:
        verbose_name = '新上线待批准资产'
        verbose_name_plural = verbose_name
        ordering = ['-c_time']
